home *** CD-ROM | disk | FTP | other *** search
/ World of Video / World of Video.iso / gfxprograms / 3dprograms / rayshade-4.0 / fixes / fix017 / zbuf.c < prev    next >
C/C++ Source or Header  |  1995-02-13  |  11KB  |  379 lines

  1. /*
  2.  * zbuf.c
  3.  *
  4.  * Add Z buffer support to Rayshade 4.0, by Mark W. Maimone (mwm@cs.cmu.edu)
  5.  *
  6.  * Rayshade is a rendering package by Craig Kolb, et al
  7.  * Copyright (C) 1989, 1991, Craig E. Kolb
  8.  * All rights reserved.
  9.  *
  10.  * This software may be freely copied, modified, and redistributed
  11.  * provided that this copyright notice is preserved on all copies.
  12.  *
  13.  * You may not distribute this software, in whole or in part, as part of
  14.  * any commercial product without the express consent of the authors.
  15.  *
  16.  * There is no warranty or other guarantee of fitness of this software
  17.  * for any purpose.  It is provided solely "as is".
  18.  *
  19.  * zbuf.c,v 4.1 1994/08/09 07:44:49 explorer Exp
  20.  *
  21.  * zbuf.c,v
  22.  * Revision 4.1  1994/08/09  07:44:49  explorer
  23.  * Bump version to 4.1
  24.  *
  25.  * Revision 1.1.1.1  1994/08/08  04:51:55  explorer
  26.  * Initial import.  This is a prerelease of 4.0.6enh3, or 4.1 possibly.
  27.  *
  28.  */
  29.  
  30. #include "rayshade.h"
  31. #include "options.h"
  32. #include "zbuf.h"
  33. #include "viewing.h"
  34.  
  35. typedef struct {
  36.     char   *s;
  37.     int       i;
  38. } PairT;
  39.  
  40. RSZbuf zbuffer;
  41.  
  42. /* Must set the proper window size before calling ZbufSetup() */
  43.  
  44. void
  45. ZbufSetup()
  46. {
  47.         int horiz = Screen.xsize;
  48.         int vert  = Screen.ysize;
  49.         int i, j;
  50.  
  51.         if (Options.zbufname == (char *)NULL)
  52.                 return;
  53.         if ((zbuffer.fzbuf = fopen (Options.zbufname, "w")) == NULL)
  54.                 RLerror(RL_PANIC, "Cannot open Z buffer file \"%s\".\n",
  55.                         Options.zbufname);
  56.         zbuffer.array = (Float **) Malloc (vert * sizeof (Float *));
  57.  
  58. /* Initialize all depths to Infinity */
  59.  
  60.         for (i = 0; i < vert; i++) {
  61.                 zbuffer.array[i] = (Float *) Malloc (horiz * sizeof (Float));
  62.                 for (j = 0; j < horiz; j++)
  63.                         zbuffer.array[i][j] = ZBUF_INF;
  64.         } /* for */
  65. } /* ZbufSetup */
  66.  
  67.  
  68. /* ZbufAdd -- Some object in pixel (x,y) is distance   dist   from the
  69.    eye.  Add it to the Z buffer if it's nearer than all other objects seen
  70.    so far.  This simple-minded storage scheme relies on the anti-aliasing
  71.    to sample the pixel at appropriate places.  It also assumes you want
  72.    the distance of the *nearest* object touching the pixel as the final
  73.    distance measure. */
  74.  
  75. void ZbufAdd (x, y, dist)
  76. Float x, y, dist;
  77. {
  78.     int j = ((int) (x + 0.5)) - Screen.minx;
  79.     int i = ((int) (y + 0.5)) - Screen.miny;
  80.     
  81.     if (zbuffer.array && i >= 0 && j >= 0 && i < Screen.ysize &&
  82.     j < Screen.xsize) 
  83.     {
  84.     Float before = zbuffer.array[i][j];
  85.     
  86.     if (before == ZBUF_INF || dist < before)
  87.         zbuffer.array[i][j] = dist;
  88.     }
  89. } /* ZbufAdd */
  90.  
  91.  
  92. /* ZbufPrint -- Write the Z buffer data to a file.  Output format is
  93.    determined by the filename, or by DEFAULT_ZBUF_TYPE.  Three formats
  94.    are available:
  95.  
  96.     HF  --  Output is written in Heightfield format
  97.     TXT --  After some opening comments, distances are written in
  98.         ascii.  Each line in the output file contains distances for
  99.         the corresponding image line, separated by a single space.
  100.     TXT3 -- After some opening comments, distances are
  101.         output as a triple: pixel coordinate and distance (e.g.:
  102.  
  103.                    0 3 3.14146
  104.  
  105.    means at position (0,3) the depth is 3.13146.  This is very
  106.    space-inefficient, but is quite portable, and can be directly read by
  107.    GNUplot for easy viewing.
  108.  
  109.         % rayshade -R 50 50 -z zbuf.dat Examples/balls.ray > balls.rle
  110.         % gnuplot
  111.         gnuplot> set term x11           [or whatever you're on]
  112.         gnuplot> set sample 2500        [for a 50x50 image]
  113.         gnuplot> set parametric         [needed to plot 3D data]
  114.         gnuplot> splot 'zbuf.dat' with lines
  115.                                         [gives a nice height map grid]
  116.         gnuplot> help set view          [info on changing viewpoint]
  117.         gnuplot> set view 45, 45        [a sample viewpoint]
  118.         gnuplot> quit
  119.  
  120.    Warning!  Distances are expected to always be positive, so background
  121.    pixels are represented by a distance of ZBUF_INF (i.e., -1000).  To get
  122.    nice looking GNUplot output you should replace all -1's with the maximum
  123.    distance.  On UNIX:
  124.  
  125.         % rayshade -R 50 50 -z zbuf.dat Examples/planet.ray > balls.rle
  126.         % awk 'BEGIN {max = -1} NF == 3 { if ($3 > max) max = $3} END \
  127.                 {print max}' < zbuf.dat         [this gives you the max]
  128.         3.69359
  129.         % sed s/-1000/3.69359/g < zbuf.dat | awk 'NF == 3 { print $1" "$2" -"$3 \
  130.                 ; next} {print}' > zbuf.plot    [replace -1 with max, make all
  131.                                                  distances negative so the
  132.                                                  plot appears rightside up]
  133.         % gnuplot
  134.                 .
  135.                 .
  136.         gnuplot> set zrange [-3.7:0]
  137.         gnuplot> splot 'zbuf.plot'
  138. */
  139.  
  140. static PairT exts[] = {
  141.     "hf",    ZBUF_HF,
  142.     "rle",    ZBUF_RLE,
  143.     "txt",    ZBUF_TXT,
  144.     "txt3",    ZBUF_TXT3,    /* silly suffix, for backward compatability */
  145.     "etxt",    ZBUF_TXT3,
  146. }; /* exts */
  147.  
  148. void ZbufPrint ()
  149. {
  150.     int type = ZsetOutputType (Options.zbufname);
  151.     int len = Screen.xsize;
  152.     int y;
  153.     FILE *fp = zbuffer.fzbuf;
  154.     char *filename = Options.zbufname;
  155.  
  156.     if (PrepareForOutput (type, fp, filename) == 0)
  157.     return;
  158. #ifdef URT
  159.     for (y = Screen.ysize-1; y >= 0; y--)
  160. #else
  161.     for (y = 0; y < Screen.ysize; y++)
  162. #endif
  163.     WriteRow (type, y + Screen.miny, fp, filename, zbuffer.array[y], len);
  164.  
  165.     NoMoreThisImage (type, fp, filename);
  166. } /* ZbufPrint */
  167.  
  168. int PrepareForOutput (type, fp, filename)
  169. int type;
  170. FILE *fp;
  171. char *filename;
  172. {
  173.     HEIGHTFIELD_SIZE i;
  174.     
  175.     if (fp == NULL) return 0;
  176.  
  177.     switch (type) {
  178.         case ZBUF_HF:
  179.         i = Screen.xsize;
  180.         if (i < Screen.ysize) i = Screen.ysize;
  181.         fwrite (&i, sizeof (HEIGHTFIELD_SIZE), 1, fp);
  182.         zbuffer.pad = i - Screen.xsize;
  183.         break;
  184.     case ZBUF_RLE:
  185.         fprintf (stderr, "Sorry, RLE output not available\n");
  186.         return 0;
  187.     case ZBUF_TXT:
  188.     case ZBUF_TXT3:
  189.         fprintf (fp, "# Rayshade Z-buffer output file for command:\n");
  190.         fprintf (fp, "#   ");
  191.         ZwriteArgv (fp, zbuffer.argv);
  192.         if (zbuffer.rayfile)
  193.         fprintf (fp, "\n# Input RAY file: \"%s\"\n", zbuffer.rayfile);
  194.         if (zbuffer.outfile)
  195.         fprintf (fp, "# Output file:    \"%s\"\n", zbuffer.outfile);
  196.         fprintf (fp, "# Resolution for this rendering is %dx%d\n",
  197.              Screen.xres, Screen.yres);
  198.         fprintf (fp, "# window from (%d,%d) to (%d,%d)\n",
  199.              Screen.minx, Screen.miny, Screen.maxx, Screen.maxy);
  200.         break;
  201.     default:
  202.         fprintf (stderr, "Error!  Unknown Z buffer type '%d'\n", type);
  203.         return 0;
  204.     } /* switch */
  205.     return 1;
  206. } /* PrepareForOutput */
  207.  
  208. WriteRow (type, y, fp, filename, row, len)
  209. int type, y;
  210. FILE *fp;
  211. char *filename;
  212. Float *row;
  213. int len;
  214. {
  215.     int i;
  216.     char *sep = "";
  217.     static float *padding = NULL;
  218.     static int pad_len = 0, vec_len = 0;
  219.     static float *vec = NULL;
  220.  
  221.     switch (type) {
  222.         case ZBUF_HF:
  223.         if (vec_len < len) {
  224.         if (vec) free (vec);
  225.         vec_len = ((len+9) / 10) * 10;
  226.         vec = (float *) malloc (sizeof (float) * vec_len);
  227.         }
  228.         for (i = 0; i < len; i++)
  229.         vec[i] = (float) row[i];
  230.         fwrite (vec, sizeof (float), len, fp);
  231.         if (zbuffer.pad) {
  232.         if (pad_len < zbuffer.pad) {
  233.             if (padding) free (padding);
  234.             pad_len = ((zbuffer.pad+9) / 10) * 10;
  235.             padding = (float *) malloc (sizeof (float) * pad_len);
  236.             for (i = 0; i < pad_len; i++) padding[i] = ZBUF_INF;
  237.         } /* if */
  238.         fwrite (padding, sizeof (float), zbuffer.pad, fp);
  239.         }
  240.         break;
  241.     case ZBUF_TXT:
  242.         for (i = 0; i < len; i++) {
  243.         fprintf (fp, "%s%g", sep, row[i]);
  244.         sep = " ";
  245.         } /* for */
  246.         fprintf (fp, "\n");
  247.         break;
  248.     case ZBUF_TXT3:
  249.         for (i = 0; i < len; i++)
  250.         fprintf (fp, "%d %d %g\n", i + Screen.minx, y, row[i]);
  251.         fprintf (fp, "\n");
  252.         break;
  253.     default:
  254.         fprintf (stderr, "*Invalid type %d in WriteRow\n", type);
  255.         break;
  256.     } /* switch */
  257. } /* WriteRow */
  258.  
  259. NoMoreThisImage (type, fp, filename)
  260. int type;
  261. FILE *fp;
  262. char *filename;
  263. {
  264.     if (type == ZBUF_HF)
  265.     if (Screen.xsize > Screen.ysize) {
  266.         int len = Screen.xsize - Screen.ysize;
  267.         int i;
  268.         float *padding = (float *) malloc (sizeof (float) * Screen.xsize);
  269.  
  270.         for (i = 0; i < Screen.xsize; i++)
  271.         padding[i] = ZBUF_INF;
  272.         while (len-- > 0)
  273.         fwrite (padding, sizeof (float), Screen.xsize, fp);
  274.         free (padding);
  275.     } /* if */
  276.     fclose (fp);
  277.     zbuffer.fzbuf = NULL;
  278. } /* NoMoreThisImage */
  279.  
  280. ZwriteArgv (fp, argv)
  281. FILE *fp;
  282. char **argv;
  283. {
  284.     char *sep = "";
  285.  
  286.     if (fp == NULL || argv == NULL) return;
  287.  
  288.     while (*argv) {
  289.     fprintf (fp, "%s%s", sep, *argv);
  290.     sep = " ";
  291.     argv++;
  292.     }
  293. } /* ZwriteArgv */
  294.  
  295. int ZsetOutputType (filename)
  296. char *filename;
  297. {
  298.     int i, len;
  299.     int type = DEFAULT_ZBUF_TYPE;
  300.  
  301.     if (filename != NULL) {
  302.     len = strlen (filename);
  303.     for (i = 0; i < sizeof (exts) / sizeof (PairT); i++)
  304.         if (len >= strlen (exts[i].s) && strcmp (exts[i].s,
  305.             filename + len - strlen (exts[i].s)) == 0) {
  306.         type = exts[i].i;
  307.         break;
  308.         } /* if */
  309.     } /* if */
  310.  
  311. /* No RLE output yet */
  312.  
  313.     if (type == ZBUF_RLE) {
  314.     fprintf (stderr,
  315.         "  (Z buffer not in available in RLE format yet, sorry)\n");
  316.     type = DEFAULT_ZBUF_TYPE;
  317.     } /* if */
  318.  
  319.     if (type) {
  320.     fprintf (stderr, "Z buffer will be written in ");
  321.     switch (type) {
  322.         case ZBUF_HF:    fprintf (stderr, "HEIGHTFIELD"); break;
  323.         case ZBUF_TXT:    fprintf (stderr, "TEXT"); break;
  324.         case ZBUF_TXT3:    fprintf (stderr, "EXPANDED TEXT"); break;
  325.         case ZBUF_RLE:    fprintf (stderr, "UTAH RASTER TOOLKIT"); break;
  326.         default:        fprintf (stderr, "UNKNOWN!!");
  327.                 type = 0; break;
  328.     } /* switch */
  329.     fprintf (stderr, " format to \"%s\"\n", Options.zbufname);
  330.     } /* if */
  331.     return type;
  332. } /* ZsetOutputType */
  333.  
  334.  
  335. #ifdef SDfl
  336.  
  337. void ZbufPrint ()
  338. {
  339.     FILE *fp = zbuffer.fzbuf;
  340.     int minx = Screen.minx, maxx = Screen.maxx;
  341.     int miny = Screen.miny, maxy = Screen.maxy;
  342.     int horiz = Screen.xsize;
  343.     int vert  = Screen.ysize;
  344.     int x, y;
  345.     
  346.     if (fp == NULL)
  347.     return;
  348.     
  349.     fprintf (fp, "# Depth Map for Rayshade output file\n");
  350.     if (zbuffer.rayfile)
  351.     fprintf (fp, "# Input RAY file: \"%s\"\n", zbuffer.rayfile);
  352.     if (zbuffer.outfile)
  353.     fprintf (fp, "# Output file:    \"%s\"\n", zbuffer.outfile);
  354.     fprintf (fp, "# Resolution for this rendering is %dx%d\n",
  355.          Screen.xres, Screen.yres);
  356.     fprintf (fp, "# window from (%d,%d) to (%d,%d)\n",
  357.          minx, miny, maxx, maxy);
  358.     fprintf (fp, "# Screen X unit vector:  (%g,%g,%g)\n",
  359.         Screen.scrnx.x, Screen.scrnx.y, Screen.scrnx.z);
  360.     fprintf (fp, "# Screen Y unit vector:  (%g,%g,%g)\n",
  361.         Screen.scrny.x, Screen.scrny.y, Screen.scrny.z);
  362.  
  363. /* Would be nice to save command-line options too */
  364.     
  365.     for (x = 0; x < horiz; x++) 
  366.     {
  367.     for (y = 0; y < vert; y++)
  368.         fprintf (fp, "%d %d %g\n", x, y, zbuffer.array[x][y]);
  369.  
  370.     fprintf (fp, "\n");
  371.  
  372.     } /* for */
  373.     
  374.     fclose (fp);
  375.     zbuffer.fzbuf = NULL;
  376.  
  377. } /* ZbufPrint */
  378. #endif
  379.